# -*- coding: utf-8 -*-
from MediaCollection.Database import Database
from MediaCollection.Audio.Cd import Cd
from Exceptions.LibraryException import LibraryException

"""
Die Artist-Klasse repräsentiert einen Künstler mit allen in der Datenbank 
gespeicherten Attributen. Über ein Objekt dieser Klasse können neue Einträge in 
die Datenbank eingefügt werden, im Gegenzug aber auch über die Id des Eintrags
in der Datenbank die entsprechenden Informationen in das Objekt eingelesen 
werden.

@author: Philipp Dermitzel
@date: 2011-04-01
@version: 1.6.1
"""

class Artist(object):
    
    """
    ----------------------------------------------------------------------------
    Konstruktor
    ----------------------------------------------------------------------------
    """
    
    """
    Der  Konstruktor. Erstellt das Objekt und liest, falls eine ID übergeben 
    wird, die entsprechenden Daten aus der Datenbank ein.
    @param id: Wird eine ID übergeben, so werden die Daten des entsprechenden 
        Artists direkt eingelesen.
    @type id: int
    @param name: Wird ein Name übergeben, so werden die Daten des entsprechenden
        Artists direkt eingelesen.
    @type name: String
    """
    def __init__(self, id = None, name = None): 
        """
        Speichert alle Informationen des Artist. Ist über C(getData()) abrufbar.
        @type: Dictionary
        """
        self.__artistData = {
            'id' : None,
            'name' : None,
            'sort' : None,
            'imgPath' : None,
            'mbId' : None
        }
        
        if id is not None:
            self.__artistData['id'] = id
            self.getDataFromDb()
        elif name is not None:
            self.__artistData['name'] = name
            self.getDataFromDb()
    
    """
    ----------------------------------------------------------------------------
    Getter und Setter
    ----------------------------------------------------------------------------
    """
    
    """
    Setzt die Attribute des Artists um diesen später erfolgreich in die 
    Datenbank einfügen zu können. Dafür sollte das übergebene Dictionary
     C(dataDict) alle eben dort beschriebenen Informationen enthalten.    
    @param dataDict: Alle benötigten Informationen zum Artist. Die momentan 
        genutzten Felder sind: id, name, sort, imgPath (Der Pfad zu dem Bild für
        den Artist und mbId (die MusicBrainz-Id).
    @type dataDict: Dictionary
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Artist
    """
    def setData(self, dataDict):
        if 'id' in dataDict:
            self.__artistData['id'] = dataDict['id']
        if 'name' in dataDict:
            self.__artistData['name'] = dataDict['name']
        if 'sort' in dataDict:
            self.__artistData['sort'] = dataDict['sort']
        if 'imgPath' in dataDict:
            self.__artistData['imgPath'] = dataDict['imgPath']
        if 'mbId' in dataDict:
            self.__artistData['mbId'] = dataDict['mbId']
        return self
    
    """
    Setzt ein einzelnen Attribut des Artist. Die momentan genutzten Felder sind:
    id, name, imgPath (Der Pfad zu dem Bild für den Artist und mbId (die 
    MusicBrainz-Id).    
    @param key: Der Schlüssel (id, name, imgPath, mbId).
    @type key: String
    @param value: Der zu setzende Wert.
    @type value: int oder String
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Artist
    """
    def setValue(self, key, value):
        if key == "id":
            self.__artistData['id'] = value
        elif key == "name":
            self.__artistData['name'] = value
        elif key == "sort":
            self.__artistData['sort'] = value
        elif key == "imgPath":
            self.__artistData['imgPath'] = value
        elif key == "mbId":
            self.__artistData['mbId'] = value
        else: 
            raise LibraryException("\"%s\" ist kein valider Parameter" %key)
        return self
    
    """
    Getter
    @return: Alle Artist-Daten.
    @rtype: Dictionary
    """
    def getData(self):
        return self.__artistData
    
    """
    Getter.
    @return: Die ID des Artists in der Datenbank.
    @rtype: int
    """
    def getId(self):
        return self.__artistData['id']
    
    """
    Getter.
    @return: Der Name des Artists.
    @rtype: String
    """
    def getName(self):
        return self.__artistData['name']
    
    """
    Getter.
    @return: Die Sortierungsschreibweise des Artists.
    @rtype: String
    """
    def getSort(self):
        return self.__artistData['sort']
        
    """
    Getter.
    @return: Der Pfad zum Bild für diesen Artist.
    @rtype: String
    """
    def getImgPath(self):
        return self.__artistData['imgPath']
     
    """
    Getter.
    @return: Die MusicBrainz-Id des Artists.
    @rtype: String
    """
    def getMbId(self):
        return self.__artistData['mbId']
        
    """
    ----------------------------------------------------------------------------
    Methoden der Klasse
    ----------------------------------------------------------------------------
    """
    
    """
    Liest die Artist-Daten aus der Datenbank.
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Artist
    """
    def getDataFromDb(self):
        db = Database()
        if self.__artistData['name'] is not None:
            arguments = {'name':self.__artistData['name']}
        elif self.__artistData['id'] is not None:
            arguments = {'id':self.__artistData['id']}
        else: raise LibraryException('Keine ID oder Name übergeben')
        
        try: 
            db.select('*', 'Artist', arguments)
            curArtist = db.dbCursor.fetchone()
            self.__artistData['id'] = curArtist[0]
            self.__artistData['name'] = curArtist[1]
            self.__artistData['sort'] = curArtist[2]
            self.__artistData['imgPath'] = curArtist[3]
            self.__artistData['mbId'] = curArtist[4]
        except: raise LibraryException('Artist nicht vorhanden')        
        return self
    
    """
    Speichert die Artist-Daten in der Datenbank.
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Artist
    """   
    def insertIntoDb(self):
        if (self.__artistData['name'] is not None):
            db = Database()
            db.savepoint("sp")
            try: 
                db.insert('Artist', {
                    'name'      : self.__artistData['name'],
                    'sort'      : self.__artistData['sort'],
                    'imgPath'   : self.__artistData['imgPath'],
                    'mbId'      : self.__artistData['mbId']
                })
                self.__artistData['id'] = db.dbCursor.lastrowid
                self.getDataFromDb()
            except:
                db.rollback("sp")
                raise LibraryException('Konnte Daten nicht einfügen')
        else: raise LibraryException('Nicht alle Daten vorhanden')
        return self
        
    """
    Löscht einen Artist aus der Datenbank.
    ACHTUNG: Hierbei werden auch alle CDs und deren Tracks gelöscht!
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Artist
    """    
    def deleteFromDb(self):
        if self.__artistData['id'] is None:
            self.getDataFromDb()
        db = Database()        
        try: 
            db.delete('Track', {'artist':self.__artistData['id']})
            db.delete('Cd', {'artist':self.__artistData['id']})
            db.delete('Artist', {'id':self.__artistData['id']})
        except: raise LibraryException('Artist nicht vorhanden')
        return self
        
    """
    Holt alle Alben eines Interpreten. Die Sortierungs-Reihenfolge kann über den
    Parameter orderBy angegeben werden. Dabei kann dieser allen Attributen eines
    C(Cd)-Objektes entsprechen.
    @param orderBy: Sortieren nach x.
    @type orderBy: String
    @return: Ein Array mit allen Alben des Artists als Cd-Objekte.
    @rtype: Array
    """
    def getArtistsAlbums(self, orderBy = 'year'):        
        self.getDataFromDb()
        db = Database()
        try:            
            db.select('id', 'Cd', {'artist':self.__artistData['id']}, 
                "ORDER BY %s" %(orderBy))
            allAlbums = db.dbCursor.fetchall()
            albumArray = []
            for album in allAlbums: albumArray.append(Cd(album[0]))
            return albumArray
        except: raise LibraryException('Artist nicht vorhanden')
    
    """
    Holt alle Artists aus der Datenbank. Die Sortierungs-Reihenfolge kann über 
    den Parameter orderBy angegeben werden. Dabei kann dieser allen Attributen 
    eines C(Artist)-Objektes entsprechen.
    @param orderBy: Sortieren nach x.
    @type orderBy: String
    @return: Ein Array mit allen Artists als Artist-Objekte.
    @rtype: Array
    """
    def getAllArtists(self, orderBy = 'name'):
        db = Database()
        try:
            db.select('id', 'Artist', {}, "ORDER BY %s" %(orderBy))
            allArtists = db.dbCursor.fetchall()
            artistArray = []
            for artist in allArtists: 
                curArtist = Artist(int(artist[0]))
                curArtist.getDataFromDb()
                artistArray.append(curArtist)
            return artistArray
        except: raise LibraryException('Konnte die Artists nicht auslesen')
